package com.jinx.zookeeper;

import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;

import java.util.concurrent.TimeUnit;

/**
 *  测试分布式api
 * @author Jinx
 * @date 2021/6/14 17:34
 */
public class ZkDemo {


    private final ZooKeeper zk;
    private boolean flag = false;
    private static final String PATH = "/jinx2";


    /**
     *   弄了一晚上   终于找到报错 KeeperErrorCode = ConnectionLoss 的原因了
     *  这个连接是异步的，在连接还未成功就开始调用api就会抛 ‘ KeeperErrorCode = ConnectionLoss for / ’ 这种异常
     *  为什么这么慢，网友说直接ip连接导致的：
     *      直接用ip去连接zk，特别慢。发现是InetAddress.getHostName()这个方法太慢导致。
     *      zk会用ip去换域名（为什么要换域名？），如果ip没被DNS收录的话会很慢。
     *      解决方法：在本地hosts文件添加ip和域名映射（域名随便给）。
     *
     *  我们只需要在连接成功后再调用我们的api就行了(还有就是不能直接创建多级节点)
     */
    public ZkDemo() throws Exception {
        String url = "192.168.153.128";

        //  这玩意是异步的
        zk = new ZooKeeper(url, 60 * 1000, watchedEvent -> {
            //  这个监控是连接成功的监控
            System.out.println("监听。。。"+watchedEvent);
            flag = true;
        });
    }


    @SuppressWarnings("unused")
    public static void main(String[] args) throws Exception {
        ZkDemo zkDemo = new ZkDemo();

        if(!zkDemo.flag){
            do {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } while (zkDemo.flag);
        }

        zkDemo.test();


        int read = System.in.read();
    }


    /**
     *  测试下zookeeper监控相关
     */
    public void test() throws Exception {
        System.out.println(zk.getChildren("/", null));

        System.out.println(zk.create(PATH, "1".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL));


        System.out.println("******************************");

        // exist（）监控的是啥？
        zk.exists(PATH, watchedEvent -> {
            System.out.println(watchedEvent.getType().getIntValue());
            System.out.println("exists   watchedEvent = " + watchedEvent);
        });


        // getData() 监控的又是啥？
        zk.getData(PATH, watchedEvent -> {
            System.out.println(watchedEvent.getType().getIntValue());
            System.out.println("getData   watchedEvent = " + watchedEvent);
        }, new Stat());

        // getChildren() 监控的又是啥？
        zk.getChildren(PATH, watchedEvent -> System.out.println("getChildren   watchedEvent = " + watchedEvent));
    }
}
